#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>

#include "config.h"

void handle_client(int sock, struct sockaddr *clnt_addr, int clnt_len);

int main() {
    int serv_sock;
    struct sockaddr_in serv_addr;

    // allocate a TCP socket
    if ((serv_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
        printf("evlog_daemon: couldn't start information service\n");
        goto error_exit;
    }

    // setup the server address information. Currently, we use 4999 as the port to listen on
    bzero(&serv_addr, sizeof(struct sockaddr_in));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(4999);

    // bind the socket to the port
    if (bind(serv_sock, (struct sockaddr *) &serv_addr, sizeof(struct sockaddr_in)) < 0) {
        printf("evlog_daemon: couldn't bind information service\n");
        goto error_exit_sock;
    }

    // setup the listener for the server
    if (listen(serv_sock, 2) < 0) {
        printf("evlog_daemon: couldn't listen on socket\n");
        goto error_exit_sock;
    }

    // loop waiting for clients and handling them
    while(1) {
        int clnt_sock;
	SOCKLEN_T clnt_len;
        struct sockaddr_in clnt_addr;

        clnt_len = sizeof(struct sockaddr_in);

	// accept a client
        if ((clnt_sock = accept(serv_sock, (struct sockaddr *) &clnt_addr, &clnt_len)) < 0) {
            printf("evlog_daemon: accept failed\n");
            goto error_exit_sock;
        }

	if (fork() == 0) {
		printf("handling %d\n", serv_sock);
		handle_client(clnt_sock, (struct sockaddr *) &clnt_addr, clnt_len);
		exit(0);
	}
    }

error_exit_sock:
    close(serv_sock);
error_exit:
    return -1;
}

void print_event(char *buf) {
	char temp_str[65536];
	short type;
	short level;
	char *value;
	char *desc;

	type = buf[0];
	level = buf[1];
	value = buf + 2;
	switch(type) {
		case 1:
			desc="INFO";
			break;
		case 2:
			desc="MEAS";
			break;
		case 3:
			desc="DEBUG";
			break;
		default:
			desc="INVALID";
			break;
	}

	snprintf(temp_str, sizeof(temp_str), "%s(%d): %s", desc, level, value);

	printf("%s\n", temp_str);
}

void handle_client(int sock, struct sockaddr *clnt_addr, int clnt_len) {
	char buf[65536];
	int read;
	int to_read;
	int amt_read;

	while(1) {

		bzero(buf, 65536);

		printf("starting read\n");

		read = recv(sock, &to_read, sizeof(int), 0);
		if (read <= 0)
			return;

		to_read = ntohs(to_read);

		printf("To Read: %d\n", to_read);

		if (to_read <= 0 || to_read > 65536)
			continue;

		amt_read = 0;
		while(to_read > 0) {
			read = recv(sock, buf + amt_read, to_read, 0);
			if (read <= 0)
				return;

			to_read -= read;
			amt_read += read;
		}

		printf("got data\n");

		print_event(buf);
	}

}

